<?php

declare(strict_types=1);

namespace App\Job;

use App\Model\Device;
use App\Model\DevicePort;
use App\Model\Normal;
use App\Model\Order;
use App\Services\DeviceService;
use App\Services\rx\RxService;
use Carbon\Carbon;
use Hyperf\AsyncQueue\Job;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\ApplicationContext;
use Swoole\Server;

class HeartEvent extends Job
{
    public $data;

    public $fd;

    public $type;

    /**
     * 任务执行失败后的重试次数，即最大执行次数为 $maxAttempts+1 次
     */
    protected int $maxAttempts = 1;
    #[inject]
    protected RxService $rxService;
    public function __construct($fd, $type, $data)
    {
        $this->fd = $fd;
        $this->type = $type;
        $this->data = $data;
    }

    public function handle()
    {


        // 获取Redis实例
        $lockKey = md5("lock:{$this->fd}{$this->type}");
        // 尝试获取锁，3秒过期时间
        $lockAcquired = redis()->set($lockKey, time(), ['NX', 'EX' => 3]);
        // 如果无法获取锁，说明3秒内已经执行过，直接返回
        if (!$lockAcquired) {
            Normal::logger(sprintf(
                'IotEvent skipped due to rate limit - FD:%d Type:%s',
                $this->fd,
                $this->type
            ), 'heart-event');
            return;
        }

        try {
            switch ($this->type) {
                case 'heartbeat':
                    $this->handleHeart();
                    break;
                default:
                    //do something
                    break;

            }
        } catch (\Exception $e) {
            Normal::logger($e->getMessage() . $e->getTraceAsString(), 'notify-event');
        }
    }

    public function handleHeart()
    {
        $device = Device::where('sn', $this->data['charger_id'])
            ->with('port')
            ->first();
        if ($device) {
            try{
                $device->last_online_at = Carbon::now();
                $device->inline = 1;
                $device->signal = $this->data['signal'];
                $device->temperature = $this->data['temperature'];
                $device->channel = $this->data['channel'];
                $device->save();
                $UnUse = [];
                foreach ($this->data['gun_status'] as $portBin => $status) {
                    if($status == 0){
                        array_push($UnUse,$portBin+1);
                    }
                    DevicePort::updateOrCreate(
                        [
                            'device_id' => $device->id,
                            'port_bin' => $portBin+1
                        ],
                        [
                            'status' => $status,
                            'sn' =>$device->sn
                        ]
                    );
                }
                $order = Order::where('device_id', $device->id)
                    ->whereIn('channel_number',$UnUse)
                    ->where('status', Order::STATUS_USING)
                    ->with('detail')
                    ->first();
                if ($order) {
                    if($order->detail){
                        $data = [
                            'sn' => $order->sn,
                            'channel_number' => $order->channel_number,
                            'number' => $order->number,
                            'stop_reason' => '2',
                            'stop_reason_text' => '端口已结束充电',
                            'duration' => $order->detail->duration,
                            'elec' => $order->detail->elec,
                            'power' => $order->detail->power
                        ];
                    }else{
                        $data = [
                            'sn' => $order->sn,
                            'channel_number' => $order->channel_number,
                            'number' => $order->number,
                            'stop_reason' => '2',
                            'stop_reason_text' => '端口已结束充电',
                            'duration' => 0,
                            'elec' => 0,
                            'power' => 0
                        ];
                    }

                    $response = DeviceService::postTcp('/callback/end', $data);
                    if ($response->getStatusCode() != 200) {
                        Normal::logger(__METHOD__ . '通知失败: ' . json_encode($this->data), 'order-event');
                    }
                }
            }catch (\Exception $e){
                Normal::logger($e->getMessage() . $e->getTraceAsString(), 'heart-event');
            }
        } else {
            Normal::logger('fd--' . $this->fd . '----heartbeat-error' . json_encode($this->data), 'heart-event');
        }
    }


}
